#include "StdAfx.h"
#include "PlanManager.h"
#include "Operator.h"
#include "RootOperator.h"
#include "IStreamOutput.h"
#include "QueryManager.h"
#include "DstreamOperator.h"
#include "IstreamOperator.h"
#include "RstreamOperator.h"
#include "ProjectionOperator.h"
#include "SelectionOperator.h"
#include "JoinOperator.h"
#include "RowWindowOperator.h"
#include "RangeWindowOperator.h"
#include "LeafOperator.h"
#include "QueryIntermediateRepresentationInterpreter.h"
#include "QueueEntity.h"
#include <sstream>
#include <boost/shared_ptr.hpp>
PlanManager* PlanManager::planManager = NULL;
PlanManager::PlanManager(void)
{

}


PlanManager::~PlanManager(void)
{
}

PlanManager* PlanManager::getInstance()
{
	if(planManager==NULL)
	{
		planManager = new PlanManager();
	}
	return planManager;
}
std::list<boost::shared_ptr<Operator> > PlanManager::getOperatorList(void)
{
	return this->operatorList;
}
void PlanManager::generateQueryPlan(boost::shared_ptr<QueryIntermediateRepresentation>queryIntermediate)
{
	 Document& queryDocument = queryIntermediate->getDocument();
	 boost::shared_ptr<Operator> rootOperator = QueryIntermediateRepresentationInterpreter::getInstance()->resolve(queryDocument);
	 addOperatorToList(rootOperator);
#ifdef DEBUG
	setOperatorIdAndQueueId();
#endif
}
void PlanManager::addOperatorToList(boost::shared_ptr<Operator>op)
{
	std::list<boost::shared_ptr<QueueEntity> > inputQueueList = op->getInputQueueList();
	if(inputQueueList.size()>0)
	{
		
	}
	std::list<boost::shared_ptr<QueueEntity> > ::iterator it;
	for(it= inputQueueList.begin();it!=inputQueueList.end();it++)
	{
		boost::shared_ptr<QueueEntity> queueEntity = *it;
		boost::shared_ptr<Operator> inputOperator = queueEntity->getInputOperator();
		addOperatorToList(inputOperator);
	}
	this->operatorList.push_back(op);
}
#ifdef DEBUG
void PlanManager::setOperatorIdAndQueueId(void)
{
	int leafOperatorNumber = 0;
	int rowwindowOperatorNumber = 0;
	int rangewindowOperatorNumber = 0;
	int selectionOperatorNumber = 0;
	int projectionOperatorNumber = 0;
	int joinOperatorNumber = 0;
	int dstreamOperatorNumber = 0;
	int istreamOperatorNumber = 0;
	int rstreamOperatorNumber = 0;
	int rootOperatorNumber = 0;
	int queueNumber = 0;
	std::list<boost::shared_ptr<Operator> >operatorList = this->operatorList;
	std::list<boost::shared_ptr<Operator> >::iterator it;
	for(it = operatorList.begin();it!=operatorList.end();it++)
	{
		boost::shared_ptr<Operator> op = *it;
		if(typeid(*op)==typeid(LeafOperator))
		{
			stringstream ss;
			leafOperatorNumber++;
			ss<<leafOperatorNumber;
			op->setId(QUERY_LEAF + "operator" +  ss.str());
		}
		else if(typeid(*op)==typeid(RowWindowOperator))
		{
			stringstream ss;
			rowwindowOperatorNumber++;
			ss<<rowwindowOperatorNumber;
			op->setId(QUERY_ROWWINDOW  + "operator" +  ss.str());
		}
		else if(typeid(*op)==typeid(RangeWindowOperator))
		{
			stringstream ss;
			rangewindowOperatorNumber++;
			ss<<rangewindowOperatorNumber;
			op->setId(QUERY_RANGEWINDOW  + "operator" +  ss.str());
		}
		else if(typeid(*op)==typeid(SelectionOperator))
		{
			stringstream ss;
			selectionOperatorNumber++;
			ss<<selectionOperatorNumber;
			op->setId(QUERY_SELECTION  + "operator" +  ss.str());
		}
		else if(typeid(*op)==typeid(ProjectionOperator))
		{
			stringstream ss;
		    projectionOperatorNumber++;
			ss<<projectionOperatorNumber;
			op->setId(QUERY_PROJECTION  + "operator" +  ss.str());
		}
		else if(typeid(*op)==typeid(JoinOperator))
		{
			stringstream ss;
			joinOperatorNumber++;
			ss<<joinOperatorNumber;
			op->setId(QUERY_JOIN  + "operator" +  ss.str());
		}
		else if(typeid(*op)==typeid(IstreamOperator))
		{
			stringstream ss;
			istreamOperatorNumber++;
			ss<<istreamOperatorNumber;
			op->setId(QUERY_ISTREAM  + "operator" +  ss.str());
		}
		else if(typeid(*op)==typeid(DstreamOperator))
		{
			stringstream ss;
			dstreamOperatorNumber++;
			ss<<dstreamOperatorNumber;
			op->setId(QUERY_DSTREAM  + "operator" +  ss.str());
		}
		else if(typeid(*op)==typeid(RstreamOperator))
		{
			stringstream ss;
			rstreamOperatorNumber++;
			ss<<rstreamOperatorNumber;
			op->setId(QUERY_RSTREAM  + "operator" +  ss.str());
		}
		else if(typeid(*op)==typeid(RootOperator))
		{
			stringstream ss;
			rootOperatorNumber++;
			ss<<rootOperatorNumber;
			op->setId(QUERY_ROOT  + "operator" +  ss.str());
		}
		std::list<boost::shared_ptr<QueueEntity> > outputQueueList;
		std::list<boost::shared_ptr<QueueEntity> >::iterator itt;
		for(itt = outputQueueList.begin();itt!=outputQueueList.end();itt++)
		{
			boost::shared_ptr<QueueEntity> queueEntity = *itt;
			queueNumber++;
			stringstream ss;
			ss<<queueNumber;
			queueEntity->setId("queue" + ss.str());
		}
	}
}
#endif